/*
' DotNetNuke?- http://www.dotnetnuke.com
' Copyright (c) 2002-2006
' by Perpetual Motion Interactive Systems Inc. ( http://www.perpetualmotion.ca )
'
' Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
' documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
' the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
' to permit persons to whom the Software is furnished to do so, subject to the following conditions:
'
' The above copyright notice and this permission notice shall be included in all copies or substantial portions 
' of the Software.
'
' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
' TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
' THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
' CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
' DEALINGS IN THE SOFTWARE.
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Reflection;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml;

using DotNetNuke;
using DotNetNuke.Common.Utilities;
using DotNetNuke.Entities.Modules;
using DotNetNuke.Entities.Modules.Actions;
using DotNetNuke.Security;
using DotNetNuke.Services.Exceptions;
using DotNetNuke.Services.Localization;
using System.Data;
using System.Text;
using System.Text.RegularExpressions;

namespace YourCompany.Modules.TweetNuke
{
    /// -----------------------------------------------------------------------------
    /// <summary>
    /// The ViewTweetNuke class displays the content
    /// </summary>
    /// <remarks>
    /// </remarks>
    /// <history>
    /// </history>
    /// -----------------------------------------------------------------------------
    partial class ViewTweetNuke : PortalModuleBase
    {

        #region Private Members

        private string strTemplate;

        #endregion

        #region Public Methods

        public bool DisplayAudit()
        {
            bool retValue = false;

            if ((string)Settings["auditinfo"] == "Y")
            {
                retValue = true;
            }

            return retValue;
        }

        #endregion

        #region Event Handlers

        /// -----------------------------------------------------------------------------
        /// <summary>
        /// Page_Load runs when the control is loaded
        /// </summary>
        /// <remarks>
        /// </remarks>
        /// <history>
        /// </history>
        /// -----------------------------------------------------------------------------
        protected void Page_Load(System.Object sender, System.EventArgs e)
        {
            try
            {
                if (!Page.IsPostBack)
                {
                    /*
                    if (((string)Settings["template"] != null) && ((string)Settings["template"] != ""))
                        strTemplate = (string)Settings["template"];
                    else
                        strTemplate = Localization.GetString("Template.Text", LocalResourceFile);
                    */
                    TweetNukeController objTweetNukes = new TweetNukeController();
                    List<TweetNukeInfo> colTweetNukes;
                    TweetNukeInfo objTweetNuke = new TweetNukeInfo();

                    //get the account information from the TweetNuke table
                    colTweetNukes = objTweetNukes.GetTweetNukes(ModuleId);

                    if (colTweetNukes.Count == 0)
                    {
                        objTweetNuke.ModuleId = ModuleId;
                        objTweetNuke.Username = objTweetNuke.Password = objTweetNuke.FollowingsCache = objTweetNuke.FollowingsToDisplay = "";
                        objTweetNukes.AddTweetNuke(objTweetNuke);
                        colTweetNukes = objTweetNukes.GetTweetNukes(ModuleId);
                    }
                    objTweetNuke = colTweetNukes.ToArray()[0];


                    //Set up edit link
                    hlEdit.NavigateUrl = this.EditUrl("ItemID", objTweetNuke.ItemId.ToString());
                    hlEdit.Visible = this.IsEditable;
                    

                    //Check if twitter account defined
                    if (objTweetNuke.Username == "")
                    {
                        lblNoTweets.Text = "No twitter account specified";
                        lblNoTweets.Visible = true;
                        rptTweetList.Visible = false;
                    }
                    else
                    {
                        //Set up new tweet textbox
                        pnAddTweet.Visible = this.IsEditable;
                        pnUserInfo.Visible = this.IsEditable;
                        txtTweet.Attributes.Add("onkeyup", "calcTxt(event);");
                        
                        try
                        {
                            rptTweetList.DataSource = getTweets(objTweetNuke);
                            rptTweetList.DataBind();
                        }
                        catch (Exception ex)
                        {
                            lblNoTweets.Text = "Error retrieving data from twitter server";
                            lblNoTweets.Visible = true;
                            rptTweetList.Visible = false;
                        }
                    }
                }
                pnTrends.Visible = true;
                Dictionary<string, string> dic = getTrends();
                rptTrends.DataSource = dic;
                rptTrends.DataBind();
            }
            catch (Exception exc) //Module failed to load
            {
                Exceptions.ProcessModuleLoadException(this, exc);
            }

        }
        
        #endregion

        protected void btnAddTweet_Click(object sender, EventArgs e)
        {
            if (txtTweet.Text != "" && txtTweet.Text.Length < 160)
            {
                TweetNukeController objTweetNukes = new TweetNukeController();
                
                //get the account information from the TweetNuke table
                List<TweetNukeInfo> colTweetNukes = objTweetNukes.GetTweetNukes(ModuleId);
                if (colTweetNukes.Count != 0)
                {
                    TweetNukeInfo objTweetNuke = colTweetNukes.ToArray()[0];
                    addTweet(objTweetNuke);
                }
            }
            Response.Redirect(Request.Url.AbsoluteUri, true);
        }

        #region Twitter Methods

        /// <summary>
        /// Get user timeline
        /// </summary>
        /// <param name="Username"></param>
        /// <param name="Password"></param>
        /// <param name="NumberofTweets"></param>
        /// <returns></returns>
        private XmlNodeList getTweets(String Username, String Password, String ScreenNameOrID, int NumberOfTweets)
        {
            string url = "http://twitter.com/statuses/user_timeline/";
            string format = "xml";
            int count = NumberOfTweets;
            if (count == 0)
            {
                count = 5;
            }
            url = url + ScreenNameOrID + "." + format + "?count=" + count;
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Credentials = new NetworkCredential(Username, Password);
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader sr = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
            string xmlString = sr.ReadToEnd();
            sr.Close();
            response.Close();

            XmlDocument xmlDoc = new XmlDocument();
            xmlDoc.Load(new StringReader(xmlString));
            XmlNodeList list = xmlDoc.GetElementsByTagName("status");
            
            return list;
        }

        /// <summary>
        /// Add new tweet
        /// </summary>
        /// <param name="objTweetNuke"></param>
        private void addTweet(TweetNukeInfo objTweetNuke)
        {
            string url = "http://twitter.com/statuses/update.xml";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded";
            request.ServicePoint.Expect100Continue = false;
            request.Credentials = new NetworkCredential(objTweetNuke.Username, objTweetNuke.Password);

            //Encode post data
            string status = "status=" + txtTweet.Text;
            UTF8Encoding encoding = new UTF8Encoding();
            byte[] data = encoding.GetBytes(status);
            request.ContentLength = data.Length;
            Stream stream = request.GetRequestStream();
            stream.Write(data, 0, data.Length);
            stream.Close();
            try
            {
                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                response.Close();
            }
            catch (WebException ex)
            {
                HttpWebResponse response = (HttpWebResponse)ex.Response;
                StreamReader sr = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
                string xmlString = sr.ReadToEnd();
            }
        }

        public DateTime parseTwitterXmlDate(string xmlDate)
        {
            string[] array = xmlDate.Split(' ');
            string[] monthsArray = { "", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
            List<string> months = new List<string>(monthsArray.Length);
            months.AddRange(monthsArray);
            string[] time = array[3].Split(':');
            DateTime date = new DateTime(int.Parse(array[5]), months.IndexOf(array[1]), int.Parse(array[2]), int.Parse(time[0]), int.Parse(time[1]), int.Parse(time[2]), DateTimeKind.Utc);
            return date.ToLocalTime();
        }

        private XmlNodeList parseXmlNodeList(List<XmlNodeList> list, int max)
        {
            XmlDocument doc = new XmlDocument();
            XmlElement root = doc.CreateElement("statuslist");
            doc.AppendChild(root);
            XmlNodeList firstList = list[0];
            list.RemoveAt(0);
            foreach (XmlNode node in firstList)
            {
                root.AppendChild(doc.ImportNode(node, true));
            }
            if (list.Count > 0)
            {
                foreach (XmlNodeList xnl in list)
                {
                    foreach (XmlNode node in xnl)
                    {
                        XmlNode child = doc.ImportNode(node, true);
                        XmlAttribute attr = doc.CreateAttribute("", "from", "");
                        attr.Value = "following";
                        child.Attributes.Append(attr);
                        DateTime date = parseTwitterXmlDate(node.SelectSingleNode("created_at").InnerText);
                        XmlNodeList currList = doc.GetElementsByTagName("status");
                        foreach (XmlNode currNode in currList)
                        {
                            DateTime currDate = parseTwitterXmlDate(currNode.SelectSingleNode("created_at").InnerText);
                            if (date > currDate) // more recent than current node
                            {
                                root.InsertBefore(child, currNode);
                                break;
                            }
                            else if (currNode.NextSibling == null) // reach the end of document
                            {
                                root.InsertAfter(child, currNode);
                            }
                            else
                            {
                                DateTime nextDate = parseTwitterXmlDate(currNode.NextSibling.SelectSingleNode("created_at").InnerText);
                                if (date > nextDate)
                                {
                                    root.InsertAfter(child, currNode);
                                    break;
                                }
                            }
                        }
                    }
                }
                XmlNodeList nodeList = doc.GetElementsByTagName("status");
                XmlDocument newDoc = new XmlDocument();
                XmlNode newRoot = newDoc.CreateElement("statuslist");
                newDoc.AppendChild(newRoot);
                int count = 0;
                foreach (XmlNode node in nodeList)
                {
                    if (count < max)
                    {
                        newRoot.AppendChild(newDoc.ImportNode(node, true));
                        count++;
                    }
                    else
                    {
                        break;
                    }
                }
                return newDoc.GetElementsByTagName("status");
            }
            return doc.GetElementsByTagName("status");
        }

        private XmlNodeList getTweets(TweetNukeInfo objTweetNuke)
        {
            List<XmlNodeList> list = new List<XmlNodeList>();
            XmlNodeList ownList = getTweets(objTweetNuke.Username, objTweetNuke.Password, objTweetNuke.Username, objTweetNuke.TweetsToDisplay);
            list.Add(ownList);
            // Set user info
            if (ownList.Count > 0)
            {
                pnUserInfo.Visible = true;
                XmlNode node = ownList.Item(0);
                XmlNode user = node["user"];
                string name = user["name"].InnerText;
                string pic = user["profile_image_url"].InnerText;
                string desc = user["description"].InnerText;
                string followers = user["followers_count"].InnerText;
                string friends = user["friends_count"].InnerText;
                string location = user["location"].InnerText;
                imgUserPic.ImageUrl = pic;
                lblUserName.Text = name;
                if (location == "")
                {
                  lblUserLoca.Visible = false;
                }
                lblLocation.Text = location;
                if (desc == "")
                {
                  lblDescription.Visible = false;
                }
                lblFollowersCount.Text = followers;
                lblFriendsCount.Text = friends;
                lblDescText.Text = desc;
            }
            if (objTweetNuke.FollowingsToDisplay != "")
            {
                string[] array = objTweetNuke.FollowingsToDisplay.Split(';');
                List<string> followings = new List<string>(array.Length);
                followings.AddRange(array);
                foreach (string id in followings)
                {
                    XmlNodeList tweets = getTweets(objTweetNuke.Username, objTweetNuke.Password, id, objTweetNuke.TweetsToDisplay);
                    list.Add(tweets);
                }
                return parseXmlNodeList(list, objTweetNuke.TweetsToDisplay);
            }
            return ownList;
        }


        private Dictionary<string, string> getTrends()
        {
            Dictionary<string, string> dic = new Dictionary<string, string>();
            string url = "http://search.twitter.com/trends.json";
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
            request.ServicePoint.Expect100Continue = false;

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            StreamReader sr = new StreamReader(response.GetResponseStream(), System.Text.Encoding.UTF8);
            string jsonString = sr.ReadToEnd();
            sr.Close();
            response.Close();
            jsonString = jsonString.Replace("\"", "");
            int start = jsonString.IndexOf('[');
            int end = jsonString.IndexOf(']');
            string trendsString = jsonString.Substring(start+2,end-start-3);
            
            string[] stringArray = Regex.Split(trendsString, "},{");
            foreach (string s in stringArray)
            {
                string[] array = Regex.Split(s, ",");
                dic.Add(array[0].Substring(5) , array[1].Substring(4));
            }
            return dic;
        }

        #endregion
    }
}

